<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>ajax全套</title>
	</head>
	<body>
		<button id="send">发送请求</button>
		<button id="abort">中断请求</button>
		<input id="file" type="file" />
		<div>进度条：<span id="progress"></span></div>

		<script>
			// 1. GET
			// 2. POST application/json（JSON数据） | application/x-www-form-urlencoded（表单数据） | multipart/form-data boundary（文件上传）
			// 3. 中断请求（abort） 进度条（progress） 超时（timeout）
			/**
			 * readyState 0: 请求未初始化，XMLHttpRequest 对象已创建，但尚未调用 open() 方法。
			 * readyState 1: 服务器连接已建立，open() 方法已调用，但send() 方法未调用。
			 * readyState 2: 请求已接收，send() 方法已调用，服务端正在处理请求。
			 * readyState 3: 请求处理中，服务器正在处理请求并返回数据。
			 * readyState 4: 请求已完成，服务器已完成响应。
			 *
			 * status:  200 请求成功；403 禁止访问；404 未找到页面；500 服务器错误。
			 */

			// 发送请求按钮
			const btn = document.querySelector('#send')
			btn.addEventListener('click', request)

			// 中断请求按钮
			const abort = document.querySelector('#abort')

			// 封装请求方法
			function request() {
				// 创建 XMLHttpRequest 实例对象
				const xhr = new XMLHttpRequest()

				// 调用open()方法，请求方式 + 请求地址 + 是否异步（默认为true，非异步会阻塞代码执行）
				// xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1?_limit=10', true)\
				xhr.open('POST', 'https://jsonplaceholder.typicode.com/todos', true)

				// 设置超时时间
				xhr.timeout = 10000

				// 设置请求头
				// xhr.setRequestHeader('Content-Type', 'application/json') // 设置请求参数数据格式为 json
				xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') // 设置请求参数数据格式为 urlencoded

				// 监听超时回调
				xhr.addEventListener('timeout', () => {
					console.log('请求超时')
				})

				// 监听进度
				xhr.addEventListener('progress', (event) => {
					console.log(`当前进度：${event.loaded}`, `总进度：${event.total}`)
					const progress = document.querySelector('#progress')
					progress.textContent = `${((event.loaded / (event.total || 100)) * 100).toFixed(2)}%`
				})

				// 监听状态请求变化 0 1 2 3 4
				// xhr.onreadystatechange = () => {
				// 	if (xhr.readyState === 4 && xhr.status === 200) {
				// 		console.log('请求成功：', xhr.responseText)
				// 	}
				// }

				// 监听状态简写方式
				xhr.addEventListener('load', () => {
					if (xhr.status === 200) {
						console.log('请求成功：', xhr.responseText)
					}
				})

				// 中断请求
				abort.addEventListener('click', () => {
					xhr.abort()
				})

				// 中断请求回调
				xhr.addEventListener('abort', () => {
					console.log('请求中断')
				})

				// 向后端发送请求和参数数据
				// GET 请求，参数拼接在地址后面的。
				// xhr.send(null)

				// POST 请求传参
				const data = {
					title: '吃饭',
					completed: false,
				}

				// json 格式参数
				// xhr.send(JSON.stringify(data))

				// urlencoded 格式参数
				xhr.send(`title=${data.title}&completed=${data.completed}`)
			}

			// ***************************************************************************************

			// 文件上传
			const file = document.querySelector('#file')

			file.addEventListener('change', (event) => {
				const files = event.target.files
				const data = new FormData()
				data.append('file', files[0])

				const xhr = new XMLHttpRequest()
				xhr.open('POST', 'https://jsonplaceholder.typicode.com/posts', true)
				// xhr.setRequestHeader('Content-Type', 'multipart/form-data') // 让浏览器自动设置请求头，它会定义 boundary 格式

				xhr.onreadystatechange = () => {
					if (xhr.readyState === 4 && xhr.status === 200) {
						console.log('上传成功：', xhr.responseText)
					}
				}

				xhr.send(data)
			})
		</script>
	</body>
</html>
